home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-17 | 16.4 KB | 532 lines | [TEXT/MPS ] |
- /*
- * This file has been changed from the original MacApp 3.1.1
- * to support the metrowerks CodeWarrior compilers C/C++ 1.1.1.
- * These changes are known *not* to work with earlier versions
- * of CodeWarrior. Every attempt though has been made to to keep
- * this file compatible with other development environments.
- *
- * Mark Anderson
- * metrowerks
- * 9/16/94
- *
- */
-
- // ObjectHeap.cp
- // Copyright © 1985-1994 by Apple Computer, Inc. All rights reserved.
-
- #ifndef PLATFORMMEMORY_H
- #include <PlatformMemory.h>
- #endif
-
- #ifndef __OBJECTHEAP__
- #include <ObjectHeap.h>
- #endif
-
-
- //========================================================================================
- // CLASS ChunkyBlock
- //========================================================================================
- #pragma segment Main
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlock::ChunkyBlock
- //----------------------------------------------------------------------------------------
-
- ChunkyBlock::ChunkyBlock()
- {
- SetBlockType(kBlockTypeId);
- SetMagicNumber(kMagicNumber);
- fNext = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlock::ChunkyBlock
- //----------------------------------------------------------------------------------------
-
- ChunkyBlock::ChunkyBlock(unsigned int sizeIndex,
- unsigned int blockIndex)
- {
- SetSizeIndex(sizeIndex);
- SetBlockIndex(blockIndex);
- SetBlockType(kBlockTypeId);
- SetMagicNumber(kMagicNumber);
- fNext = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlock::GetChunk
- //----------------------------------------------------------------------------------------
-
- Chunk* ChunkyBlock::GetChunk(FW_BlockSize blkSize)
- {
- Chunk *chk
- = (Chunk *) ((FW_BytePtr) this - sizeof(SChunkHeader) - blkSize * GetBlockIndex());
- return chk;
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlock::IsBusy
- //----------------------------------------------------------------------------------------
-
- Boolean ChunkyBlock::IsBusy(FW_BlockSize blockSize)
- {
- return this->GetChunk(blockSize)->IsBlockBusy(GetBlockIndex());
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlock::SetBusy
- //----------------------------------------------------------------------------------------
-
- void ChunkyBlock::SetBusy(FW_BlockSize blockSize, Boolean busy)
- {
- this->GetChunk(blockSize)->SetBlockBusy(GetBlockIndex(), busy);
- }
-
-
- //========================================================================================
- // Chunk
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // Chunk::Chunk
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Chunk::Chunk(short blocksPerChunk,
- unsigned int sizeIndex,
- FW_BlockSize blockSize)
- {
- fHeader.fBlockBusyBits = 0;
- void* blkPtr = (void *) ((FW_BytePtr) this + sizeof(SChunkHeader));
- for (unsigned int i = 0; i < blocksPerChunk; i++)
- {
- ChunkyBlock *blk = new(blkPtr)ChunkyBlock(sizeIndex, i);
- blkPtr = (void *) ((FW_BytePtr) blkPtr + blockSize);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // Chunk::IsBlockBusy
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean Chunk::IsBlockBusy(unsigned int whichBlock)
- {
- unsigned short mask = 0x0001 << whichBlock;
-
- return (fHeader.fBlockBusyBits & mask) != 0;
- }
-
- //----------------------------------------------------------------------------------------
- // Chunk::SetBlockBusy
- //----------------------------------------------------------------------------------------
-
- void Chunk::SetBlockBusy(unsigned int whichBlock, Boolean busy)
- {
- unsigned short mask = 0x0001 << whichBlock;
-
- if (busy)
- fHeader.fBlockBusyBits |= mask;
- else
- fHeader.fBlockBusyBits &= ~mask;
- }
-
- //----------------------------------------------------------------------------------------
- // Chunk::GetBlock
- //----------------------------------------------------------------------------------------
-
- ChunkyBlock* Chunk::GetBlock(unsigned int blkIndex, FW_BlockSize blkSize)
- {
- ChunkyBlock * blk
- = (ChunkyBlock *) ((FW_BytePtr) this + sizeof(SChunkHeader) + blkIndex * blkSize);
- return blk;
- }
-
-
- //========================================================================================
- // ObjectHeap
- //========================================================================================
-
- const FW_BlockSize ObjectHeap::kDefaultBlockSizes[] = {sizeof(ChunkyBlock), 10, 14, 18, 0};
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::ObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ObjectHeap::ObjectHeap(unsigned long initialSize,
- unsigned long incrementSize,
- short blocksPerChunk) :
- BestFitHeap(initialSize, incrementSize),
- fBlockSizes(kDefaultBlockSizes)
- {
- #ifdef DEBUG
- CompilerCheck();
- #endif
-
- fBlocksPerChunk = blocksPerChunk;
-
- for (fNumberOfBlockSizes = 0; fBlockSizes[fNumberOfBlockSizes]; fNumberOfBlockSizes++)
- ;
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::ObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ObjectHeap::ObjectHeap(const FW_BlockSize* blockSizes,
- unsigned long initialSize,
- unsigned long incrementSize,
- short blocksPerChunk) :
- BestFitHeap(initialSize, incrementSize),
- fBlockSizes(blockSizes)
- {
- #ifdef DEBUG
- CompilerCheck();
- #endif
-
- fBlocksPerChunk = blocksPerChunk;
-
- for (fNumberOfBlockSizes = 0; fBlockSizes[fNumberOfBlockSizes]; fNumberOfBlockSizes++)
- ;
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::IObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::IObjectHeap()
- {
- this->IBestFitHeap();
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::~ObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ObjectHeap::~ObjectHeap()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoAllocate
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void* ObjectHeap::DoAllocate(FW_BlockSize size, FW_BlockSize& allocatedSize)
- {
- if (size + ChunkyBlock::kBusyOverhead > fBlockSizes[fNumberOfBlockSizes - 1])
- return BestFitHeap::DoAllocate(size, allocatedSize);
- else
- {
- unsigned int sizeIndex = this->SizeIndex(size);
- allocatedSize = fBlockSizes[sizeIndex] - ChunkyBlock::kBusyOverhead;
- return this->AllocateBlock(sizeIndex);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoBlockSize
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_BlockSize ObjectHeap::DoBlockSize(const void* ptr) const
- {
- ChunkyBlock *block
- = (ChunkyBlock *) ((FW_BytePtr) ptr - ChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == BestFitBlock::kBlockTypeId)
- return BestFitHeap::DoBlockSize(ptr);
- else
- return fBlockSizes[block->GetSizeIndex()] - ChunkyBlock::kBusyOverhead;
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoFree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::DoFree(void* ptr)
- {
- ChunkyBlock *block
- = (ChunkyBlock *) ((FW_BytePtr) ptr - ChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == BestFitBlock::kBlockTypeId)
- BestFitHeap::DoFree(ptr);
- else
- this->FreeBlock(block);
- }
-
- #ifdef DEBUG
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoIsValidBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean ObjectHeap::DoIsValidBlock(void* ptr) const
- {
- Boolean isBlockValid = false;
-
- ChunkyBlock *block
- = (ChunkyBlock *) ((FW_BytePtr) ptr - ChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == BestFitBlock::kBlockTypeId)
- isBlockValid = BestFitHeap::DoIsValidBlock(ptr);
- else
- isBlockValid
- = block->GetSizeIndex() <= fNumberOfBlockSizes &&
- block->GetBlockIndex() <= fBlocksPerChunk &&
- block->GetMagicNumber() == (unsigned int) ChunkyBlock::kMagicNumber;
-
- return isBlockValid;
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoReset
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::DoReset()
- {
- ChunkyBlockStack clr;
-
- for (int i = 0; i < fNumberOfBlockSizes; i++)
- fFreeLists[i] = clr;
-
- BestFitHeap::DoReset();
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::AllocateBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void *ObjectHeap::AllocateBlock(unsigned int sizeIndex)
- {
- if (fFreeLists[sizeIndex].Top() == NULL)
- this->CreateNewChunk(sizeIndex);
-
- ChunkyBlock * blk = fFreeLists[sizeIndex].Pop();
- if (blk != NULL)
- {
- blk->SetBusy(fBlockSizes[sizeIndex], true);
- return (void *) ((FW_BytePtr) blk + ChunkyBlock::kBusyOverhead);
- }
- else
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::CreateNewChunk
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::CreateNewChunk(unsigned int sizeIndex)
- {
- FW_BlockSize allocatedSize;
- FW_BlockSize allocSize = sizeof(SChunkHeader) + fBlocksPerChunk * fBlockSizes[sizeIndex];
- Chunk * chk = new(BestFitHeap::DoAllocate(allocSize, allocatedSize))Chunk(fBlocksPerChunk, sizeIndex, fBlockSizes[sizeIndex]);
- if (chk != NULL)
- {
- for (unsigned int i = 0; i < fBlocksPerChunk; i++)
- {
- ChunkyBlock * blk = chk->GetBlock(i, fBlockSizes[sizeIndex]);
- blk->SetBusy(fBlockSizes[sizeIndex], false);
- fFreeLists[sizeIndex].Push(blk);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::FreeBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::FreeBlock(ChunkyBlock* blk)
- {
- blk->SetBusy(fBlockSizes[blk->GetSizeIndex()], false);
- fFreeLists[blk->GetSizeIndex()].Push(blk);
-
- // Check to see if all blocks in this block's Chunk are free, if so then free the
- // Chunk.
-
- Chunk *chk = blk->GetChunk(fBlockSizes[blk->GetSizeIndex()]);
- if (!chk->IsBusy())
- {
- // Remove blocks in this Chunk from the free list. This is the achililles hill
- // of the Heap. Its difficult to remove blocks from a singly linked list
- // rapidly.
-
- void *begAddr = chk;
- void *endAddr = (void *) ((FW_BytePtr) chk +
- sizeof(SChunkHeader) +
- fBlocksPerChunk * fBlockSizes[chk->GetSizeIndex()]);
- fFreeLists[chk->GetSizeIndex()].RemoveRange(begAddr, endAddr);
- BestFitHeap::DoFree(chk);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::SizeIndex
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- unsigned int ObjectHeap::SizeIndex(FW_BlockSize size)
- {
- for (unsigned int i = 0; i < fNumberOfBlockSizes; i++)
- if (size + ChunkyBlock::kBusyOverhead <= fBlockSizes[i])
- return i;
-
- // Uh oh! An internal error:
-
- PLATFORM_DEBUGGER_STRING("Internal error in ObjectHeap::SizeIndex");
-
- return 0xFFFFFFFF; // the former way of handling the internal error
- // we leave it in to defeat an xlC warning
- }
-
- #ifdef DEBUG
- //----------------------------------------------------------------------------------------
- // ObjectHeap::CompilerCheck
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::CompilerCheck()
- {
- BestFitHeap::CompilerCheck();
-
- ChunkyBlock block;
-
- block.SetSizeIndex(0xF);
- block.SetBlockIndex(0xE);
- block.SetBlockType(ChunkyBlock::kBlockTypeId);
- block.SetMagicNumber(0xC);
-
- PLATFORM_ASSERT(block.GetSizeIndex() == 0xF);
- PLATFORM_ASSERT(block.GetBlockIndex() == 0xE);
- PLATFORM_ASSERT(block.GetBlockType() == ChunkyBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetBlockType() != BestFitBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetMagicNumber() == 0xC);
-
- block.SetSizeIndex(0x7);
- block.SetBlockIndex(0x6);
- block.SetBlockType(BestFitBlock::kBlockTypeId);
- block.SetMagicNumber(0x4);
-
- PLATFORM_ASSERT(block.GetSizeIndex() == 0x7);
- PLATFORM_ASSERT(block.GetBlockIndex() == 0x6);
- PLATFORM_ASSERT(block.GetBlockType() == BestFitBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetBlockType() != ChunkyBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetMagicNumber() == 0x4);
- }
- #endif
-
- //========================================================================================
- // ChunkyBlockStack
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlockStack::ChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ChunkyBlockStack::ChunkyBlockStack()
- {
- fHead.SetNext(NULL);
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlockStack::ChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ChunkyBlockStack::ChunkyBlockStack(const ChunkyBlockStack& blk) :
- fHead(blk.fHead)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlockStack::operator=
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ChunkyBlockStack& ChunkyBlockStack::operator=(const ChunkyBlockStack& blk)
- {
- fHead = blk.fHead;
- return *this;
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlockStack::Pop
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ChunkyBlock* ChunkyBlockStack::Pop()
- {
- ChunkyBlock * blk = fHead.GetNext();
- fHead.SetNext(blk->GetNext());
- return blk;
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlockStack::Push
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ChunkyBlockStack::Push(ChunkyBlock* blk)
- {
- blk->SetNext(fHead.GetNext());
- fHead.SetNext(blk);
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlockStack::RemoveRange
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ChunkyBlockStack::RemoveRange(void *begAddr, void *endAddr)
- {
- ChunkyBlock *prevBlk = &fHead;
- ChunkyBlock *curBlk = fHead.GetNext();
-
- while (curBlk != NULL)
- {
- void *curAddr = curBlk;
-
- if (curAddr >= begAddr && curAddr <= endAddr)
- {
- prevBlk->SetNext(curBlk->GetNext());
- curBlk = curBlk->GetNext();
- }
- else
- {
- prevBlk = curBlk;
- curBlk = curBlk->GetNext();
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlockStack::Top
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ChunkyBlock* ChunkyBlockStack::Top()
- {
- return fHead.GetNext();
- }
-
- //----------------------------------------------------------------------------------------
- // ChunkyBlockStack::~ChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ChunkyBlockStack::~ChunkyBlockStack()
- {
- }
-
-